﻿using LightCAD.Three;
using static LightCAD.Three.WebGLMorphtargets;

namespace QdStruct
{
    public class BeamAttribute : CptAttribute
    {
        public BeamAttribute(string category, string subCategorys) : base(category, subCategorys)
        {

        }
        public const string BuiltinUuid = "{389b0f72-aa24-4d0d-af4d-c35bb87a0243}";

        public override LcComponentDefinition GetBuiltinCpt(string subCategory)
        {
            return new QdBeamDef(BuiltinUuid,"内置", "结构梁");
        }
    }
    [BeamAttribute("结构梁", "结构梁")]
    public class QdBeamDef : LcComponentDefinition
    {
        static QdBeamDef()
        {
            CptTypeParamsDef<QdBeamDef>.ParamsDef = new ParameterSetDefinition {
                new ParameterDefinition { DataType = LcDataType.String, Name = "MaterialId", DisplayName = "材质", },
            };
        }
        public QdBeamDef()
        {
            this.TypeParameters = new LcParameterSet(CptTypeParamsDef<QdBeamDef>.ParamsDef);
        }
        public QdBeamDef(string uuid, string name, string subCategory) : base(uuid, name, "结构梁", subCategory, new LcParameterSet(CptTypeParamsDef<QdBeamDef>.ParamsDef))
        {
            this.Parameters = new ParameterSetDefinition
            {
                new ParameterDefinition(){ Name = "Lines",DisplayName="梁线", DataType=LcDataType.CurveArray },
                new ParameterDefinition(){ Name = "Width",DisplayName="起始梁宽", DataType=LcDataType.Double },
                new ParameterDefinition(){ Name = "Height",DisplayName="起始梁高", DataType=LcDataType.Double },
                new ParameterDefinition(){ Name = "Bottom",DisplayName="起始梁底高", DataType=LcDataType.Double },
                new ParameterDefinition(){ Name = "SecondWidth",DisplayName="结束梁宽", DataType=LcDataType.Double },
                new ParameterDefinition(){ Name = "SecondHeight",DisplayName="结束梁高",DataType= LcDataType.Double},
                new ParameterDefinition(){ Name = "SecondBottom",DisplayName="结束梁底高",DataType= LcDataType.Double},
             };
            var mat = MaterialManager.GetMaterial(MaterialManager.ConcreteUuid);
            this.Solid3dProvider = new Solid3dProvider(name) { AssignMaterialsFunc = (c, s) => new LcMaterial[] { mat } };
            this.Curve2dProvider = new Curve2dProvider(name)
            {
                GetCurve2dsFunc = (pset) =>
                {
                    var curve2ds = new List<Curve2d>();
                    var lines = pset.GetValue<Curve2d[]>("Lines");
                    var width = pset.GetValue<double>("Width");
                    var secondWidth = pset.GetValue<double>("SecondWidth");
                    if (secondWidth <= 0)
                        secondWidth = width;
                    foreach (var curve in lines)
                    {
                        if (curve is Line2d line)
                        {
                            var normal = line.Dir.RotateAround(new Vector2(),Math.PI/2);
                            var startLP = line.Start.Clone().AddScaledVector(normal, width / 2);
                            var startRP = line.Start.Clone().AddScaledVector(normal,- width / 2);
                            var endLP = line.End.Clone().AddScaledVector(normal, secondWidth / 2);
                            var endRP = line.End.Clone().AddScaledVector(normal, -secondWidth / 2);
                            curve2ds.Add(new Line2d(startLP.Clone(), startRP.Clone()));
                            curve2ds.Add(new Line2d(startRP.Clone(), endRP.Clone()));
                            curve2ds.Add(new Line2d(endRP.Clone(), endLP.Clone()));
                            curve2ds.Add(new Line2d(endLP.Clone(), startLP.Clone()));
                        }else
                        if (curve is Arc2d arc)
                        {
                            var lArc = arc.Clone() as Arc2d;
                            lArc.Radius = arc.Radius - width / 2;
                            var lps=lArc.GetPoints(1);
                            var rArc = arc.Clone() as Arc2d;
                            rArc.Radius = arc.Radius + width / 2;
                            var rps = rArc.GetPoints(1);
                            curve2ds.Add(lArc);
                            curve2ds.Add(rArc);
                            curve2ds.Add(new Line2d(lps.First().Clone(), rps.First().Clone()));
                            curve2ds.Add(new Line2d(lps.Last().Clone(), rps.Last().Clone()));
                        }
                    }
                    return new Curve2dGroupCollection() { new Curve2dGroup()
                        {
                            Curve2ds = curve2ds.ToListEx()
                        }
                    };
                }
            };

        }
    }
    public class QdBeamInstance : LcComponentInstance
    {
        public double Width { get => Parameters.GetValue<double>("Width"); set => Set("Width", value); }
        public double Height { get => Parameters.GetValue<double>("Height"); set => Set("Height", value); }
        public double Bottom { get => Parameters.GetValue<double>("Bottom"); set => Set("Bottom", value); }
        public double SecondWidth { get => Parameters.GetValue<double>("SecondWidth"); set => Set("SecondWidth", value); }
        public double SecondHeight { get => Parameters.GetValue<double>("SecondHeight"); set => Set("SecondHeight", value); }
        public double SecondBottom { get => Parameters.GetValue<double>("SecondBottom"); set => Set("SecondBottom", value); }

        public Curve2d[] Lines { get => Parameters.GetValue<Curve2d[]>("Lines"); set => Set("Lines", value); }

        public QdBeamInstance(QdBeamDef wallDef) : base(wallDef)
        {
            this.Type = StructElementType.Beam;
        }
        public void Set(string name, object val)
        {
            OnPropertyChangedBefore(name, this.Parameters[name], val);
            this.Parameters.SetValue(name, val);
            OnPropertyChangedAfter(name, this.Parameters[name], val);
        }

    }
}